<!DOCTYPE html>
<title>Using a parser - nearley.js - JS Parsing Toolkit</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="nearley.js is a simple, fast, and powerful parser toolkit for JavaScript." />
<style>
body {
    font-family: BlinkMacSystemFont, -apple-system, Helvetica Neue, Open Sans, Ubuntu, Arial, Helvetica, sans-serif;
    font-weight: 300;
    font-size: 15pt;
    margin: 0px;
    padding: 0px;
}

#main a {
    color: #55a;
}
#main a:visited {
    color: #55a;
}
#main a:hover {
    color: #259;
}

h1 {
    font-size: 1.2em;
    font-weight: normal;
    letter-spacing: 0.2em;
    text-align: center;
    margin:  0em;
    padding: 1em;
}

h1 a {
    color: #559;
    text-decoration: none;
}

h1 a:hover {
    color: orange;
    cursor: pointer;
}

#version {
    background: orange;
    border-radius: 50%;
    font-weight: bold;
    color: white;
    width: 3em;
    height: 3em;
    display: inline-block;
    text-align: center;
    line-height: 3em;
    letter-spacing: 0em;
}

h2 {
    font-size: 1.5em;
    margin-top: 2em;
}
h3 {
    margin-top: 3em;
}
h4 {
    margin-top: 3em;
}

.center {
    padding-left: 2em;
    padding-right: 2em;
    margin-left: auto;
    margin-right: auto;
}
#main {
    max-width: 35em;
}

#main p, ul, ol {
    line-height: 1.5em;
    margin-bottom: 1em;
}

#main li {
    margin-top: 1em;
    margin-bottom: 1em;
}

#main ul li {
    list-style: none;
    min-width: 10em;
}
#main ul li:before {
    display: inline-block;
    content: "\2014";
    margin-left: -1.5em;
    width: 1.5em;
    position: absolute;
}

#main textarea {
    width: 100%;
    height: 20em;
    resize: none;
    margin-top: 5px;
    margin-bottom: 5px;

    font-family: menlo, monaco, monospace;
    font-size: 10pt;
    padding: 5px;

    border: none;
    border-left: solid 1px #aaa;
}
#main textarea:focus {
    outline: none;
}

#main img {
    display: block;
    margin-left: auto;
    margin-right: auto;
    max-width: 100%;
}
img + .caption {
    text-align: center;
    font-size: 0.7em;
    color: #aaa;
}

#footer {
    margin-top: 10em;
    color: #aaa;
    font-size: 0.7em;
    padding: 5em;
}

code {
    margin-left: 0.2em;
    margin-right: 0.2em;
    padding: 0.2em;
    border-radius: 0.2em;
    background-color: #eee;
}

pre code {
    border-radius: 0.5em;
    padding: 0.5em;
    display: block;
    overflow: auto;
}


ol {
    counter-reset: tutorial-counter;
    position: relative;
}

ol li {
    list-style: none;
}

ol li:before {
    content: counter(tutorial-counter);
    counter-increment: tutorial-counter;

    font-weight: bold;
    border-radius: 50%;
    background-color: #559;
    width: 2em;
    height: 2em;
    display: inline-block;
    text-align: center;
    line-height: 2em;
    color: white;

    margin-left: -2em;

    position: absolute;
    left: 1em;
}

input[type="text"] {
    border: none;
    font-family: monospace;
    font-size: 1em;
    color: #559;
}

input[type="text"]:focus {
    outline: none;
}


nav {
    border-bottom: 2px solid #559;
    background: #fafafa;
}
nav ul {
    padding: 0;
    margin: 0;
}
nav ul a {
    text-decoration: none;
    color: #334;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0.25em 0.5em; */
}
.page {
    display: block;
}

.page-title-active,
.page-heading-active a {
    color: #66f;
}

.page-heading {
    display: block;
    padding-left: 1.5em;
}


@media screen and (min-width: 36rem) {
    nav {
        position: fixed;
        width: 16rem;
        left: 0;
        top: 0;
        bottom: 0;
        white-space: nowrap;
        overflow-y: auto;
        font-size: 1rem;
        border-bottom: none;
        border-right: 2px solid #559;
    }
    body.docs-page {
        margin-left: 16rem;
    }
}

/* highlight.js */

.hljs{display:block;overflow-x:auto;padding:0.5em;background:#F0F0F0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888888}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-selector-pseudo{color:#BC6060}.hljs-literal{color:#78A960}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}


</style>

<body class="docs-page">

<a href="https://github.com/kach/nearley" class="github-corner"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
<nav id="nav">
    <h1><a href="/">nearley<span style="color: #559;">.js</span><span id="version">2.20.1</span></a></h1>
    <ul>
        <li class="page"><a href="/docs/index">Home</a>
        <li class="page"><a href="/docs/getting-started">Getting started</a>
        <li class="page"><a href="/docs/grammar">Writing a parser</a>
        <li class="page">
            <a href="#" class="page-title-active">Using a parser</a>
            <ul>
                <li class="page-heading"><a href="#a-note-on-ambiguity">A note on ambiguity</a>
                <li class="page-heading"><a href="#catching-errors">Catching errors</a>
                <li class="page-heading"><a href="#accessing-the-parse-table">Accessing the parse table</a>
                <li class="page-heading"><a href="#using-preprocessors">Using preprocessors</a>
                <li class="page-heading"><a href="#whats-next">What’s next?</a>
            </ul>
        </li>
        <li class="page"><a href="/docs/tokenizers">Tokenizers</a>
        <li class="page"><a href="/docs/tooling">Tooling</a>
        <li class="page"><a href="/docs/how-to-grammar-good">How to grammar good</a>
        <li class="page"><a href="/docs/using-in-frontend">Compiling in browsers</a>
        <li class="page"><a href="/docs/glossary">Glossary</a>
    </ul>
</nav>

<div id="main" class="center">

<h2>Using a parser</h2>
<p>This section describes nearley’s parser API.</p>
<p>Once you have compiled a <code>grammar.ne</code> file to a <code>grammar.js</code> module, you can
then use nearley to instantiate a <code>Parser</code> object.</p>
<p>First, import nearley and your grammar.</p>
<pre><code class="language-js">const nearley = require(&quot;nearley&quot;);
const grammar = require(&quot;./grammar.js&quot;);</code></pre>
<p>Note that if you are parsing in the browser, you can simply include
<code>nearley.js</code> and <code>grammar.js</code> in <code>&lt;script&gt;</code> tags.</p>
<p>Next, use the grammar to create a new <code>nearley.Parser</code> object.</p>
<pre><code class="language-js">// Create a Parser object from our grammar.
const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));</code></pre>
<p>Once you have a <code>Parser</code>, you can <code>.feed</code> it a string to parse. Since nearley
is a <em>streaming</em> parser, you can feed strings more than once. For example, a
REPL might feed the parser lines of code as the user enters them:</p>
<pre><code class="language-js">// Parse something!
parser.feed(&quot;if (true) {&quot;);
parser.feed(&quot;x = 1&quot;);
parser.feed(&quot;}&quot;);
// or, parser.feed(&quot;if (true) {x=1}&quot;);</code></pre>
<p>Finally, you can query the <code>.results</code> property of the parser.</p>
<pre><code class="language-js">// parser.results is an array of possible parsings.
console.log(parser.results);
// [{&#39;type&#39;: &#39;if&#39;, &#39;condition&#39;: ..., &#39;body&#39;: ...}]</code></pre>
<h3 id="a-note-on-ambiguity">A note on ambiguity</h3>
<p>Why is <code>parser.results</code> an array? Sometimes, a grammar can parse a particular
string in multiple different ways. For example, the following grammar parses
the string <code>&quot;xyz&quot;</code> in two different ways.</p>
<pre><code class="language-ne">x -&gt; &quot;xy&quot; &quot;z&quot;
   | &quot;x&quot; &quot;yz&quot;</code></pre>
<p>Such grammars are <em>ambiguous</em>. nearley provides you with <em>all</em> the parsings. In
most cases, however, your grammars should not be ambiguous (parsing ambiguous
grammars is inefficient!). Thus, the most common usage is to simply query
<code>parser.results[0]</code>.</p>
<p>You might like to check first that <code>parser.results.length</code> is exactly 1; if
there is more than one result, then your grammar is ambiguous!</p>
<h3 id="catching-errors">Catching errors</h3>
<p>nearley is a <em>streaming</em> parser: you can call <code>feed()</code> as many times as you
like. This means there are two ways parsing can go wrong.</p>
<p>Consider the simple parser below for the examples to follow.</p>
<pre><code class="language-js">main -&gt; &quot;Cow goes moo.&quot; {% function(d) {return &quot;yay!&quot;; } %}</code></pre>
<p>If nearley gets <strong>partway through the chunk</strong> you fed, and parsing cannot
continue, then nearley will throw an error whose <code>offset</code> property is the index
of the offending token. There is no way to recover from this by feeding more
data.</p>
<pre><code class="language-js">try {
    parser.feed(&quot;Cow goes% moo.&quot;);
} catch (parseError) {
    console.log(&quot;Error at character &quot; + parseError.offset); // &quot;Error at character 9&quot;
}</code></pre>
<p>Errors are nicely formatted for you:</p>
<pre><code>Error: Syntax error at line 1 col 9:

1 Cow goes% moo.
          ^

Unexpected &quot;%&quot;</code></pre><p><strong>After <code>feed()</code> finishes</strong>, the <code>results</code> array will contain all possible
parsings.</p>
<p>If there are no possible parsings given the current input, but in the <em>future</em>
there <em>might</em> be results if you feed it more strings, then nearley will
temporarily set the <code>results</code> array to the empty array, <code>[]</code>.</p>
<pre><code class="language-js">parser.feed(&quot;Cow &quot;);  // parser.results is []
parser.feed(&quot;goes &quot;); // parser.results is []
parser.feed(&quot;moo.&quot;);  // parser.results is [&quot;yay!&quot;]</code></pre>
<p>If you’re done calling <code>feed()</code>, but the array is still empty, this indicates
“unexpected end of input”. Make sure to check there’s at least one result.</p>
<p>If there’s more than one result, that indicates ambiguity–see above.</p>
<h3 id="accessing-the-parse-table">Accessing the parse table</h3>
<p>If you are familiar with the Earley parsing algorithm, you can access the
internal parse table using <code>Parser.table</code> (this, for example, is how
<code>nearley-test</code> works). One caveat, however: you must pass the <code>keepHistory</code>
option to nearley to prevent it from garbage-collecting inaccessible columns of
the table.</p>
<pre><code class="language-js">const nearley = require(&quot;nearley&quot;);
const grammar = require(&quot;./grammar&quot;);

const parser = new nearley.Parser(
    nearley.Grammar.fromCompiled(grammar),
    { keepHistory: true }
);


parser.feed(...);
console.log(parser.table);</code></pre>
<h3 id="using-preprocessors">Using preprocessors</h3>
<p>By default, <code>nearleyc</code> compiles your grammar to JavaScript. However, you can
instead choose to compile to CoffeeScript or TypeScript by adding
<code>@preprocessor coffee</code> or <code>@preprocessor typescript</code> at the top of your grammar
file. This can be useful to write your postprocessors in a different language,
and to get type annotations if you wish to use nearley in a statically typed
dialect of JavaScript.</p>
<h4 id="typescript-preprocessor-changes">Typescript Preprocessor Changes</h4>
<p>If you have recently upgraded to a newer version of nearley, you might have run
into an issue with <code>error TS2345</code> talking about a variable
<code>missing the following properties from type &#39;CompiledRules&#39;: ParserStart, ParserRules</code>
This is a result of a change in the output format of the grammar, but is very easily fixed.
Just change the way you import the grammar from <code>import * as grammar from &quot;./path/to/grammar&quot;</code>
to <code>import grammar from &quot;./path/to/grammar&quot;</code> and everything should compile nicely again.</p>
<h3 id="whats-next">What’s next?</h3>
<p>Now that you know how to use parsers, <a href="tokenizers">learn how to add a tokenizer to speed
things up!</a></p>


    <div id="footer"><p>nearley is MIT-licensed. It's maintained by <a
    href="http://hardmath123.github.io">Hardmath123</a> (<a
    href="http://github.com/Hardmath123">Github</a>). You're welcome to
    leave questions, comments, advice, or ideas as Github issues. And
    feel free to fork nearley with your own experiments!<br/>
    
    <a href="https://js.org" target="_blank" title="JS.ORG | JavaScript Community">
    <img src="https://logo.js.org/dark_horz.png" width="102" alt="JS.ORG Logo"/></a>
</div>

<script id="highlight-js" async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>
document.querySelector('#highlight-js').addEventListener('load', function() {
    [].slice.apply(document.querySelectorAll('pre code')).forEach(function(b) {
        hljs.highlightBlock(b)
    })
})
</script>


<script>
window.addEventListener('scroll', onScroll)
window.addEventListener('resize', onScroll)

var timeout
function onScroll(e) {
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(scrollEnd, 50)
}

function scrollEnd() {
  var headings = document.querySelectorAll('h3')
  var offset = 60
  for (var i=headings.length; i--; ) {
    var h3 = headings[i]
    if (h3.offsetTop < window.scrollY + offset) {
      var cur = document.querySelector('.page-heading-active')
      if (cur) cur.className = 'page-heading'
      document.querySelector('a[href="#' + h3.id + '"]').parentNode.className = 'page-heading page-heading-active'
      return
    }
  }
}
</script>

<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-46120535-5', 'auto');
ga('send', 'pageview');
</script>

